﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_GL_COMMON_H
#define _UXS_GL_COMMON_H

#pragma once

#include "GLEnums.h"
#include "../../OS/Base/OSTypes.h"

namespace UX_STL
{
namespace GLShell
{
	using namespace UXTypesExt;

#ifdef UX_GL_DIRECT_STATE_ACCESS
#	define UX_GL_DSA( _y, _n )	_y
#else
#	define UX_GL_DSA( _y, _n )	_n
#endif	// UX_GL_DIRECT_STATE_ACCESS



	// core //
	class GLStatistic;
	//class GLObjectManager;
	//class GLStateManager;
	class GLBuffer;
	class GLSubMesh;
	class GLMesh;
	class GLRenderTarget;
	class GLFrameBuffer;
	class GLRenderBuffer;
	class GLSystemDrawBuffer;
	class GLSampler;
	class GLSamplerSW;
	class GLTexture;
	class GLTexture2D;
	class GLTexture2DArray;
	class GLTextureCube;
	class GLTextureCubeArray;
	class GLTexture3D;
	class GLTexture2DMS;
	class GLTexture2DMSArray;
	class GLTextureBuffer;
	class GLTextureDynBuffer;
	class GLQuery;
	class GLSyncObject;
	class GLSystemSync;
	class GLTransformFeedback;
	class GLShader;
	class GLProgram;
	class GLProgramPipeline;

	// extension //
	class GLViewport;
	//class GLMatrixStack;
	class GLBatchRender;
	class GLSystem;


	typedef GLDEBUGPROCARB	PGLDebugProc_t;
	

	
#pragma pack(push, 1)

	//
	// Vertex Attrib
	//

	struct GLVertexAttrib
	{
		uint				uOffset;
		uint16				uStride;
		uint16				uDivisor;
		gl_vertex::type		eType;
		uint8				uLocation;
		uint8				uCount;
		bool				bNormalize	: 1;	// can be true if bInteger and bLong is false
		bool				bInteger	: 1;
		bool				bLong		: 1;
		///
		GLVertexAttrib():
			uCount(0), uStride(0), uOffset(0), eType(gl_vertex::FLOAT), uDivisor(0),
			uLocation(-1), bNormalize(false), bInteger(false), bLong(false) {}
		
		GLVertexAttrib(uint8 loc, uint8 count, uint16 stride, uint offset, gl_vertex::type vert, bool norm = false,
						bool b_int = false, bool b_long = false, uint16 divisor = 0):
			uCount(count), uStride(stride), uOffset(offset), eType(vert), uDivisor(divisor),
			uLocation(loc), bNormalize(norm), bInteger(b_int), bLong(b_long) {}
	};


	//
	// Vertex Attrib Extended
	//

	struct GLVertexAttribExt
	{
		GLuint				uBuffer;
		uint				uOffset;
		uint16				uStride;
		uint16				uDivisor;
		gl_vertex::type		eType;
		uint8				uLocation;
		uint8				uCount;
		bool				bNormalize	: 1;	// can be true if bInteger and bLong is false
		bool				bInteger	: 1;
		bool				bLong		: 1;
		///
		GLVertexAttribExt():
			uBuffer(0), uCount(0), uStride(0), uOffset(0), eType(gl_vertex::FLOAT), uDivisor(0),
			uLocation(-1), bNormalize(false), bInteger(false), bLong(false) {}
		
		GLVertexAttribExt(GLuint buf, const GLVertexAttrib &attr):
			uBuffer(buf), uCount(attr.uCount), uStride(attr.uStride), uOffset(attr.uOffset),
			eType(attr.eType), bNormalize(attr.bNormalize), uDivisor(attr.uDivisor),
			uLocation(attr.uLocation), bInteger(attr.bInteger), bLong(attr.bLong) {}

		GLVertexAttribExt(GLuint buf, uint8 loc, uint8 count, uint16 stride, uint offset, gl_vertex::type vert,
						  bool norm, bool b_int = false, bool b_long = false, uint16 divisor = 0):
			uBuffer(buf), uCount(count), uStride(stride), uOffset(offset), eType(vert), bNormalize(norm),
			uDivisor(divisor), uLocation(loc), bLong(b_long), bInteger(b_int) {}
	};


	//
	// Vertex Attrib Info
	//

	struct GLVertexAttribInfo
	{
		gl_vertex::type		eType;
		uint8				uLocation;
		uint8				uCount;
		///
		GLVertexAttribInfo():
			eType(gl_vertex::FLOAT), uLocation(-1), uCount(0) {}

		GLVertexAttribInfo(uint8 loc, uint8 count, gl_vertex::type type):
			eType(type), uLocation(loc), uCount(count) {}

		GLVertexAttribInfo(const GLVertexAttrib &attr):
			eType(attr.bNormalize ? gl_vertex::FLOAT : attr.eType), uLocation(attr.uLocation), uCount(attr.uCount) {}

		GLVertexAttribInfo(const GLVertexAttribExt &attr):
			eType(attr.bNormalize ? gl_vertex::FLOAT : attr.eType), uLocation(attr.uLocation), uCount(attr.uCount) {}

		bool operator > (const GLVertexAttribInfo &right) const {
			return uLocation > right.uLocation;
		}

		bool operator == (const GLVertexAttribInfo &right) const {
			return eType == right.eType and uLocation == right.uLocation and uCount == right.uCount;
		}

		bool operator != (const GLVertexAttribInfo &right) const {
			return not ( *this == right );
		}
	};

	
	//
	// Texture Layer
	//
	
	struct GLTexLayer
	{
		gl_texture::type	eTarget;
		GLuint				uID;
		///
		GLTexLayer(): eTarget(gl_texture::TEXTURE_2D), uID(0) {}
		GLTexLayer(gl_texture::type target, GLuint id): eTarget(target), uID(id) {}
	};


	//
	// Texture Layer Extended
	//

	struct GLTexLayerEx
	{
		gl_texture::type	eTarget;
		GLuint				uID,
							uSampler;
		///
		GLTexLayerEx(): eTarget(gl_texture::TEXTURE_2D), uID(0), uSampler(0) {}
		GLTexLayerEx(gl_texture::type target, GLuint id, GLuint sampler): eTarget(target), uID(id), uSampler(sampler) {}
	};

#pragma pack(pop)


	typedef array< GLVertexAttrib >		GLVerticesAttribs_t;
	typedef array< GLVertexAttribExt >	GLVerticesAttribsExt_t;
	typedef array< GLVertexAttribInfo >	GLVerticesAttribsInfo_t;
	typedef array< GLBuffer *>			GLBuffers_t;
	
	typedef static_array< GLVertexAttribInfo, UX_MAX_VERTEX_ATTRIBS >	va_info_array_t;
	typedef static_array< GLVertexAttribExt, UX_MAX_VERTEX_ATTRIBS >	va_array_t;


#ifdef UX_GL_BASEOBJECT_OVERRIDE
	UX_GL_BASEOBJECT_OVERRIDE
#else
# ifndef UX_GL_BASEOBJECT_DEFINED
	
	//
	// GL Base Object
	//

	class UX_EXPORT GLBaseObject
	{
	private:
		GLBaseObject(const GLBaseObject &) {}
		void operator = (const GLBaseObject &) {}

	public:
		GLBaseObject() {}
		virtual ~GLBaseObject() {}
		virtual void Release() { delete this; }

		//virtual void Destroy() = 0;
		//virtual bool IsValid() const = 0;
	};

# endif	// UX_GL_BASEOBJECT_DEFINED
#endif	// UX_GL_BASEOBJECT_OVERRIDE

//-------------------------------------------------------------------

}	// GLShell
}	// UX_STL

#endif	// _UXS_GL_COMMON_H